using System;
using System.Collections.Generic;
using System.Text;

namespace Fuzzy
{
    public class SingletonFuzzySet:FuzzySet
    {
        public static double error = 0.001;
        private double argumentValue;
        private double singletonValue;

        public SingletonFuzzySet(FuzzyLinguisticVariable fuzzyLinguisticVariable, double argumentValue, double singletonValue)
            : base(fuzzyLinguisticVariable)
        {
            this.argumentValue = argumentValue;
            this.singletonValue = singletonValue;
        }
        
        public SingletonFuzzySet(FuzzyLinguisticVariable fuzzyLinguisticVariable, string name, double argumentValue, double singletonValue)
            :base(fuzzyLinguisticVariable, name)
        {
            this.argumentValue = argumentValue;
            this.singletonValue = singletonValue;
        }

        public override double Membership(double x)
        {
            if (Math.Abs(x-argumentValue) <= error)
                return singletonValue;
            else 
                return 0.0;
        }

        public override double[][] AlphaCut(double alpha)
        {
            if ((alpha <= singletonValue) && (alpha > 0.0))
                return new double[][] { new double[]{argumentValue, argumentValue} };
            else if (alpha <= 0.0)
                return new double[][] { new double[]{ fuzzyLinguisticVariable.DomainMin, fuzzyLinguisticVariable.DomainMax } };
            else
                return new double[0][];
        }

        public override double[][] StrictAlphaCut(double alpha)
        {
            if ((alpha < singletonValue) && (alpha >= 0.0))
                return new double[][] { new double[]{ argumentValue, argumentValue } };
            else if (alpha < 0.0)
                return new double[][] { new double[]{ fuzzyLinguisticVariable.DomainMin, fuzzyLinguisticVariable.DomainMax } };
            else
                return new double[0][];
        }

        internal override FuzzySet Union(FuzzySet fuzzySet, bool mayRedirect)
        {
            if (fuzzySet.FuzzyLinguisticVariable != fuzzyLinguisticVariable)
                throw new FuzzyException("The 2 fuzzy sets belongs to different fuzzy linguistic variables.");

            if (mayRedirect)
                return fuzzySet.Union(this, false);

            return new ComplexFuzzySet(fuzzyLinguisticVariable, FuzzyOperationEnum.SNorm, this, fuzzySet);
        }

        internal override FuzzySet Intersection(FuzzySet fuzzySet, bool mayRedirect)
        {
            if (fuzzySet.FuzzyLinguisticVariable != fuzzyLinguisticVariable)
                throw new FuzzyException("The 2 fuzzy sets belongs to different fuzzy linguistic variables.");
 
            return new SingletonFuzzySet(fuzzyLinguisticVariable, argumentValue, FuzzyUniverse.FuzzyOperation.TNorm(singletonValue, fuzzySet.Membership(argumentValue)));
        }

        public override FuzzySet Complement()
        {
            return new ComplexFuzzySet(fuzzyLinguisticVariable, FuzzyOperationEnum.Complement, this);
        }

        public override double GetDefuzzifiedValue()
        {
            if (FuzzyUniverse.Defuzzification is COADefuzzification)
                return argumentValue;
            else
                return base.GetDefuzzifiedValue();
        }

        public override double Sup()
        {
            return singletonValue;
        }
    }
}
